package eu.codlab.androidemu.services;

import java.io.IOException;

import eu.codlab.game.gameba.Emulator;
import eu.codlab.game.gameba.EmulatorViewControl;
import eu.codlab.game.gameba.nonem.input.GameKeyListener;
import eu.codlab.game.gameba.nonem.input.Keyboard;
import eu.codlab.game.gameba.nonem.input.Trackball;
import eu.codlab.game.gameba.nonem.input.VirtualKeypad;
import eu.codlab.src.game.R;


import android.app.Activity;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothSocket;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.KeyEvent;
import android.view.View;
import android.view.View.OnFocusChangeListener;
import android.view.View.OnKeyListener;
import android.widget.TextView;
import android.widget.Toast;

public class ConnectedDevice extends Activity implements GameKeyListener {
	private static final int GAMEPAD_LEFT_RIGHT =
			(Emulator.GAMEPAD_LEFT | Emulator.GAMEPAD_RIGHT);
	private static final int GAMEPAD_UP_DOWN =
			(Emulator.GAMEPAD_UP | Emulator.GAMEPAD_DOWN);
	private static final int GAMEPAD_DIRECTION =
			(GAMEPAD_UP_DOWN | GAMEPAD_LEFT_RIGHT);
	private final static String TAG="Bluetooth";
	BluetoothAdapter mBluetoothAdapter;
	BluetoothSocket tmp = null;
	private EmulatorViewControl keypad = null;
	private Trackball trackball = null;
	private Keyboard keyboard = null;

	private BluetoothState _state = BluetoothState.NOTCONNECTED;

	private void setState(BluetoothState state){
		_state = state;
		refreshState();
	}

	private boolean isConnected(){
		return tmp != null && _state == BluetoothState.CONNECTED;
	}

	private void refreshState(){
		runOnUiThread(new Runnable(){
			public void run(){
				int str=BluetoothStateHelper.getResourceFromBluetoothState(_state);
				TextView txt = (TextView)findViewById(R.id.state);
				if(txt != null)
					txt.setText(str);
			}
		});
	}
	public void onCreate(Bundle savedInstanceState){
		super.onCreate(savedInstanceState);
		this.setContentView(R.layout.gba_bluetooth);
		mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();


		// create physical keyboard and trackball
		//keyboard = new Keyboard(emulatorView, this);
		trackball = new Trackball(keyboard, this);

		keypad = (EmulatorViewControl) findViewById(R.id.keypad);
		keypad.getVirtualKeypad().setGameKeyListener(this);
		View v = (View)findViewById(R.principal.adview);
		if(v != null){
			v.setOnKeyListener(new OnKeyListener(){

				@Override
				public boolean onKey(View arg0, int keyCode, KeyEvent event) {
					if(keyboard != null)
						return keyboard.onKey(arg0, keyCode, event);
					return false;
				}

			});
		}
		keypad.requestFocus();
		keypad.setOnFocusChangeListener(new OnFocusChangeListener(){

			@Override
			public void onFocusChange(View arg0, boolean arg1) {
				if(arg1 == false){
					keypad.requestFocus();
				}
			}

		});

		Intent serverIntent = new Intent(this, DeviceListActivity.class);
		startActivityForResult(serverIntent, 42);
	}

	public void onPause(){
		if(tmp != null && isConnected())
			try{
				tmp.close();
				setState(BluetoothState.CLOSED);
			}catch(Exception e){
			}
		setState(BluetoothState.CLOSED);
		super.onPause();
	}

	public void onDestroy(){
		if(tmp != null && isConnected())
			try{
				tmp.close();
				setState(BluetoothState.CLOSED);
			}catch(Exception e){
			}
		setState(BluetoothState.CLOSED);
		super.onDestroy();
	}
	public void onActivityResult(int requestCode, int resultCode, Intent data) {
		switch (requestCode) {
		case 42:
			// When DeviceListActivity returns with a device to connect
			if (resultCode == Activity.RESULT_OK) {
				connectDevice(data, true);
			}
			break;
		case 43:
			// When the request to enable Bluetooth returns
			if (resultCode == Activity.RESULT_OK) {
				// Bluetooth is now enabled, so set up a chat session
				//
			} else {
				// User did not enable Bluetooth or an error occured
				Log.d("Bluetooth", "BT not enabled");
				Toast.makeText(this, "error", Toast.LENGTH_SHORT).show();
				finish();
			}
		}
	}

	private void connectDevice(Intent data, boolean secure) {
		setState(BluetoothState.CONNECTING);
		// Get the device MAC address
		String address = data.getExtras()
				.getString(DeviceListActivity.EXTRA_DEVICE_ADDRESS);
		// Get the BLuetoothDevice object
		BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(address);
		// Attempt to connect to the device
		connect(device, secure);
	}

	public synchronized void connect(BluetoothDevice device, boolean secure) {
		Log.d(TAG, "connect to: " + device);

		// Get a BluetoothSocket for a connection with the
		// given BluetoothDevice
		try {
			tmp = device.createRfcommSocketToServiceRecord(BluetoothServerService.MY_UUID);
			mBluetoothAdapter.cancelDiscovery();
			tmp.connect();
			setState(BluetoothState.CONNECTED);
		} catch (IOException e) {
			setState(BluetoothState.CLOSED);
			e.printStackTrace();
		}
	}


	@Override
	public void onGameKeyChanged() {
		int states = 0;
		//states |= keyboard.getKeyStates();
		states |= keypad.getVirtualKeypad().getKeyStates();

		if ((states & GAMEPAD_DIRECTION) != 0)
			trackball.reset();
		else
			states |= trackball.getKeyStates();

		// resolve conflict keys
		if ((states & GAMEPAD_LEFT_RIGHT) == GAMEPAD_LEFT_RIGHT)
			states &= ~GAMEPAD_LEFT_RIGHT;
		if ((states & GAMEPAD_UP_DOWN) == GAMEPAD_UP_DOWN)
			states &= ~GAMEPAD_UP_DOWN;

		setKeyStates(states);
	}

	public boolean onKeyUp(int keyCode, KeyEvent event){
		Log.d("onKey","Up");
		if(keyCode == KeyEvent.KEYCODE_BACK)
			this.finish();
		
		if(keyboard != null &&
				this.keyboard.onKey(keypad, keyCode, event))
			return true;
		return super.onKeyUp(keyCode, event);
	}

	public boolean onKeyDown(int keyCode, KeyEvent event) {
		Log.d("onKey","Down");
		if(keyCode == KeyEvent.KEYCODE_BACK)
			this.finish();
		
		if(keyboard != null &&
				this.keyboard.onKey(keypad, keyCode, event))
			return true;
		return super.onKeyUp(keyCode, event);
	}

	public void setKeyStates(int states){
		if(isConnected()){
			byte b1 = (byte) (states % 256);
			byte b0 = (byte) ((states - b1) / 256);
			byte []b = new byte[]{b0, b1, 2, 2};
			try {
				tmp.getOutputStream().write(b);
			} catch (IOException e) {
				setState(BluetoothState.CLOSED);
				e.printStackTrace();
			}
		}
	}

}
